package com.xyy.saas.payment.adapter.channel.fm;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.adapter.PaymentAdapter;
import com.xyy.saas.payment.adapter.channel.fm.client.SpringClient;
import com.xyy.saas.payment.adapter.channel.fm.config.BankConfigManager;
import com.xyy.saas.payment.adapter.channel.fm.config.OpenParameters;
import com.xyy.saas.payment.cores.bo.OpenPayBo;
import com.xyy.saas.payment.cores.bo.QueryCreateAllPayBo;
import com.xyy.saas.payment.cores.enums.OpenPayChannelEnum;
import com.xyy.saas.payment.dao.model.ApplypayUserInfo;
import com.xyy.saas.payment.exception.PaymentException;
import com.xyy.saas.payment.manage.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.pojo.bo.*;
import com.xyy.saas.payment.pojo.domain.QueryAccountBalanceDO;
import com.xyy.saas.payment.pojo.domain.QueryMerchantDayBalanceDO;
import com.xyy.saas.payment.pojo.dto.OpenPayDto;
import com.xyy.saas.payment.pojo.dto.QueryAccountDto;
import com.xyy.saas.payment.service.ApplypayUserInfoService;
import com.xyy.saas.payment.service.PayAccountService;
import com.xyy.saas.payment.util.AmountCastUtil;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.LeafUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class FuminAdapter implements PaymentAdapter {

    @Autowired
    private LeafUtil leafUtil;

    @Autowired
    private SpringClient springClient;

    @Autowired
    private BankConfigManager bankConfigManager;
    @Autowired
    private ApplypayUserInfoService applypayUserInfoService;
    @Autowired
    private PayAccountService payAccountService;

    @Override
    public QueryCreateAllPayBo queryCreateAllPay(String accountId, String businessIdType) throws PaymentException {
        log.info("FuminAdapter#queryCreateAllPay accountId:{}, businessIdType:{}", accountId, businessIdType);
        long beginTime = System.currentTimeMillis();
        String merchantNo = bankConfigManager.getFuminBankMch(businessIdType);
        JSONObject object = new JSONObject();
        object.put("merchant_no", merchantNo);
        object.put("cust_merchant_no", getAdapterAccountId(accountId));
        object.put("client_serial_no", leafUtil.getSnowflakeId());
        OpenParameters.Builder builder = new OpenParameters.Builder();
        builder.apiName("com.fbank.open-api.api.v1.allpay.queryCreateAllPay").param(object.toJSONString());
        JSONObject response;

        try {
            response = springClient.send0(builder.build(), merchantNo);
        }
        catch(Exception ex) {
            log.error("FuminAdapter#queryCreateAllPay merchantNo:" + merchantNo + ",accountId:" + accountId + ",V:" + businessIdType, ex);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }

        log.info("FuminAdapter#queryCreateAllPay response:{} costTime:{}", response.toJSONString() , System.currentTimeMillis() - beginTime);
        Map<String, String> headParam = JSONUtils.parse2Map(response.getString("head"), String.class, String.class);

        if(headParam == null || !"000000".equals(headParam.get("rsp_code"))) {
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR,
                    headParam == null ? ResultCodeEnum.CHANNEL_CONNECT_ERROR.getDisplayMsg() : headParam.get("rsp_msg"));
        }

        Map<String, Object> bodyParam = JSONUtils.parse2Map(response.getString("body"), String.class, Object.class);
        QueryCreateAllPayBo result = new QueryCreateAllPayBo();
        result.setStatus(String.valueOf(bodyParam.get("create_merchant_status")));
        result.setMessage(String.valueOf(bodyParam.get("message")));
        List<OpenPayBo> openPayBoList = new ArrayList<>();
        List<Object> powerList = (List<Object>) bodyParam.get("power_list");
        if(CollectionUtils.isNotEmpty(powerList)) {
            for (Object obj : powerList) {
                Map<String, String> map = (Map<String, String>) obj;
                OpenPayBo openPayBo = new OpenPayBo();
                openPayBo.setOpenPayStatus(map.get("open_pay_status"));
                openPayBo.setSubMchid(map.get("sub_mchnt_id"));
                openPayBo.setMessage(map.get("message"));
                openPayBo.setPowerId(map.get("power_id"));
                openPayBoList.add(openPayBo);
            }
        }
        result.setOpenPayList(openPayBoList);
        return result;
    }

    @Override
    public Map<String, Boolean> queryOpenPay(String accountId, String businessIdType) throws PaymentException {
        log.info("FuminAdapter#queryOpenPay accountId:{}, businessIdType:{}", accountId, businessIdType);
        long beginTime = System.currentTimeMillis();
        String merchantNo = bankConfigManager.getFuminBankMch(businessIdType);
        JSONObject object = new JSONObject();
        object.put("merchant_no", merchantNo);
        object.put("cust_merchant_no", getAdapterAccountId(accountId));
        object.put("client_serial_no", leafUtil.getSnowflakeId());
        OpenParameters.Builder builder = new OpenParameters.Builder();
        builder.apiName("com.fbank.open-api.api.v1.allpay.queryPayChannel").param(object.toJSONString());
        JSONObject response;
        try {
            response = springClient.send0(builder.build(), merchantNo);
        }
        catch(Exception ex) {
            log.error("FuminAdapter#queryOpenPay merchantNo:" + merchantNo + ",accountId:" + accountId + ",V:" + businessIdType, ex);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }

        log.info("FuminAdapter#queryOpenPay response:{} costTime:{}", response.toJSONString() , System.currentTimeMillis() - beginTime);
        Map<String, String> headParam = JSONUtils.parse2Map(response.getString("head"), String.class, String.class);

        if(headParam == null || !"000000".equals(headParam.get("rsp_code"))) {
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR,
                    headParam == null ? ResultCodeEnum.CHANNEL_CONNECT_ERROR.getDisplayMsg() : headParam.get("rsp_msg"));
        }

        JSONArray array = response.getJSONObject("body").getJSONArray("status_data");
        Map<String, Boolean> result = new HashMap<>();

        for(int i = 0; i < array.size(); i++) {
            JSONObject o = array.getJSONObject(i);
            result.put(o.getString("power_id"), "SUCCESS".equals(o.getString("open_pay_status")));
        }

        return result;
    }

    @Override
    public OpenPayBo openPay(OpenPayDto openPayDto) throws PaymentException{
        // 0.补充参数
        String merchantNo = bankConfigManager.getFuminBankMch(openPayDto.getBusinessIdType());
        openPayDto.setMerchantNo(merchantNo);
        openPayDto.setClientSerialNo(leafUtil.getSnowflakeId());

        log.info("FuminAdapter#openPay openPayDto：{}", JSONObject.toJSONString(openPayDto));
        long beginTime = System.currentTimeMillis();

        // 当开通功能为微信公众号，小程序，固定二维码，APP时，必须先经过这个接口完成微信特约商户配置的绑定。
        // if(OpenPayChannelEnum.WX.getChannel().equals(openPayDto.getOpenPayChannel())) {
        //    openPay0(merchantNo, openPayDto.getCustMerchantNo(), openPayDto.getPowerId());
        // }

        OpenParameters.Builder builder = new OpenParameters.Builder();
        builder.apiName("com.fbank.open-api.api.v1.allpay.atlOpenPay").param(openPayDto.getJSONStringParam());
        JSONObject response;

        try {
            response = springClient.send0(builder.build(), openPayDto.getMerchantNo());
        }
        catch(Exception ex) {
            log.error("FuminAdapter#openPay openPayDto:{}", openPayDto.getJSONStringParam(), ex);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }

        log.info("FuminAdapter#openPay request:{} openPayDto: {} response:{} costTime:{}",
                openPayDto.getJSONStringParam(), JSONObject.toJSONString(openPayDto), response.toJSONString() , System.currentTimeMillis() - beginTime);
        Map<String, String> headParam = JSONUtils.parse2Map(response.getString("head"), String.class, String.class);

        if(headParam == null || !"000000".equals(headParam.get("rsp_code"))) {
            /**
             * 幂等判断
             */
            if(!"OAP100002".equals(headParam.get("rsp_code")) && !"OAP100003".equals(headParam.get("rsp_code"))) {
                throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR,
                        headParam == null ? ResultCodeEnum.CHANNEL_CONNECT_ERROR.getDisplayMsg() : headParam.get("rsp_msg"));
            }
        }

        Map<String, String> body = JSONUtils.parse2Map(response.getString("body"), String.class, String.class);
        OpenPayBo result = new OpenPayBo();
        if(null != body) {
            String subMchid = body.get("sub_mchnt_id");
            result.setSubMchid(subMchid);

            if (OpenPayChannelEnum.WX.getChannel().equals(openPayDto.getOpenPayChannel()) && !StringUtils.isEmpty(subMchid)) {
                // 更新微信特约商户号
                String accountId = payAccountService.getAccountIdByBusiness(openPayDto.getBusinessIdType(), openPayDto.getBusinessId());
                ApplypayUserInfo oldApplyPayUserInfo = applypayUserInfoService.queryUserInfoByAccountId(accountId);
                if(null != oldApplyPayUserInfo) {
                    ApplypayUserInfo upd = new ApplypayUserInfo();
                    upd.setId(oldApplyPayUserInfo.getId());
                    upd.setSubMchid(subMchid);
                    if (applypayUserInfoService.updateByPrimaryKeySelective(upd) < 1) {
                        log.warn("OpenAccountServiceImpl#openPay update sub_mchid fail. account:{}, upd:{}", accountId, JSONUtils.toJSON(upd));
                    }
                }
            }
        }
        return result;
    }

    @Override
    public UserBo queryAccount(QueryAccountDto param) throws PaymentException {
        String merchantNo = bankConfigManager.getFuminBankMch(param.getBusinessIdType());
        JSONObject requestParam = new JSONObject();
        //日志流水号
        requestParam.put("client_serial_no", leafUtil.getSnowflakeId());
        //商户号
        requestParam.put("merchant_no", merchantNo);
        requestParam.put("cust_merchant_no", getAdapterAccountId(param.getUserId()));
        requestParam.put("account_no", param.getThirdUserId());
        OpenParameters.Builder builder = new OpenParameters.Builder();
        builder.apiName("com.fbank.open-api.api.v1.account.queryAccountBal")
                .param(requestParam.toJSONString());
        String response;
        try {
            response = springClient.send(builder.build(), merchantNo);
        } catch (Exception e) {
            log.error("FuminAdapter#queryAccount param:{} response:{}", JSON.toJSONString(param), e);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }
        log.info("FuminAdapter#queryAccount request:{} response:{}", JSONUtils.toJSON(requestParam), response);
        JSONObject responseParam = JSON.parseObject(response);
        Map<String, String> headParam = JSONUtils.parse2Map(responseParam.getString("head"), String.class, String.class);
        if (!"000000".equals(headParam.get("rsp_code"))) {
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR, headParam.get("rsp_msg"));
        }
        Map<String, String> bodyParam = JSONUtils.parse2Map(responseParam.getString("body"), String.class, String.class);
        UserBo userBo = new UserBo();
        userBo.setAvailableBalance(AmountCastUtil.castYuan2FenLong(bodyParam.get("availableBalance")));
        userBo.setWithdrawableBalance(AmountCastUtil.castYuan2FenLong(bodyParam.get("availableBalance")));
        userBo.setFrozenAmount(AmountCastUtil.castYuan2FenLong(bodyParam.get("frozenAmount")));
        return userBo;
    }

    /**
     * 查询余额明细
     *
     * @param queryAccountBalanceDO
     * @throws PaymentException
     */
    public QueryFuminRecordBo queryBalanceRecord(QueryAccountBalanceDO queryAccountBalanceDO) throws PaymentException {
        log.info("FuminAdapter#queryBalanceRecord 入参信息：{} ", JSONObject.toJSONString(queryAccountBalanceDO));
        try {
            String merchantNo = bankConfigManager.getFuminBankMch(queryAccountBalanceDO.getBusinessOrderType());
            JSONObject jsonObject = new JSONObject();
            //商户号
            jsonObject.put("merchant_no", merchantNo);
            //调用方id
            jsonObject.put("cust_merchant_no", getAdapterAccountId(queryAccountBalanceDO.getUserId()));
            //日志流水号
            jsonObject.put("client_serial_no", leafUtil.getSnowflakeId());
            //当前页
            jsonObject.put("page_no", queryAccountBalanceDO.getPageNo());
            //每页数量
            jsonObject.put("page_size", 20);
            //企富通账户号
            jsonObject.put("account_no", queryAccountBalanceDO.getThirdUserId());
            //查询开始时间
            jsonObject.put("trade_start_date", queryAccountBalanceDO.getBeginTime());
            //查询结束时间
            jsonObject.put("trade_end_date", queryAccountBalanceDO.getEndTime());

            OpenParameters.Builder builder = new OpenParameters.Builder();
            builder.apiName("com.fbank.open-api.api.v1.accountpayment.balanceChangeRecordQuery")
                    .param(jsonObject.toJSONString());
            String response = springClient.send(builder.build(), merchantNo);
            log.info("FuminAdapter#queryBalanceRecord the TestTransfer request:{} response:{} ", JSONUtils.toJSON(jsonObject), response);
            JSONObject responseParam = JSON.parseObject(response);
            Map<String, String> headParam = JSONUtils.parse2Map(responseParam.getString("head"), String.class, String.class);
            if (!"000000".equals(headParam.get("rsp_code"))) {
                throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR.getCode(), headParam.get("rsp_msg"));
            }
            JSONObject bodyParam = JSONUtils.parse2Object(responseParam.getString("body"), JSONObject.class);
            QueryFuminRecordBo queryFuminRecordBo = buildQueryFuminRecordBo(bodyParam);
            return queryFuminRecordBo;
        } catch (PaymentException e) {
            throw e;
        } catch (Exception e) {
            log.error("FuminAdapter#queryBalanceRecord error queryAccountBalanceDO:{}", JSON.toJSONString(queryAccountBalanceDO), e);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }

    }

    /**
     * 查询托底户日终余额
     * @param queryMerchantDayBalanceDO
     * @return
     */
    public QueryDayBalanceRecordBo queryDayBalanceRecord(QueryMerchantDayBalanceDO queryMerchantDayBalanceDO) throws PaymentException {
        log.info("FuminAdapter#queryDayBalanceRecord 入参信息：{} ", JSONObject.toJSONString(queryMerchantDayBalanceDO));
        try {
            String merchantNo = bankConfigManager.getFuminBankMch(queryMerchantDayBalanceDO.getBusinessOrderType());
            JSONObject jsonObject = new JSONObject();
            //商户号
            jsonObject.put("merchant_no", merchantNo);
            //日志流水号
            jsonObject.put("client_serial_no", leafUtil.getSnowflakeId());
            //当前页
            jsonObject.put("page_no", queryMerchantDayBalanceDO.getPageNo());
            //每页数量
            jsonObject.put("page_size", queryMerchantDayBalanceDO.getPageSize());
            //查询开始时间
            jsonObject.put("start_date", queryMerchantDayBalanceDO.getStartTime());
            //查询结束时间
            jsonObject.put("end_date", queryMerchantDayBalanceDO.getEndTime());

            OpenParameters.Builder builder = new OpenParameters.Builder();
            builder.apiName("com.fbank.open-api.api.v1.account.merchantDayBalanceQuery")
                    .param(jsonObject.toJSONString());
            String response = springClient.send(builder.build(), merchantNo);
            log.info("FuminAdapter#queryDayBalanceRecord the TestTransfer request:{} response:{} ", JSONUtils.toJSON(jsonObject), response);
            JSONObject responseParam = JSON.parseObject(response);
            Map<String, String> headParam = JSONUtils.parse2Map(responseParam.getString("head"), String.class, String.class);

            if(!"000000".equals(headParam.get("rsp_code"))) {
                throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR.getCode(), headParam.get("rsp_msg"));
            }

            JSONObject bodyParam = JSONUtils.parse2Object(responseParam.getString("body"), JSONObject.class);
            return buildDayBalanceRecord(bodyParam);
        }
        catch(PaymentException e) {
            throw e;
        }
        catch(Exception e) {
            log.error("FuminAdapter#queryBalanceRecord error queryAccountBalanceDO:{}", JSON.toJSONString(queryMerchantDayBalanceDO), e);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }
    }

    /**
     * 查询托底户最后一条交易明细
     * @param queryMerchantDayBalanceDO
     * @return
     */
    public QueryDayBalanceRecordBo queryMerchantRecord(QueryMerchantDayBalanceDO queryMerchantDayBalanceDO) throws PaymentException {
        log.info("FuminAdapter#queryMerchantRecord 入参信息：{} ", JSONObject.toJSONString(queryMerchantDayBalanceDO));
        try {
            String merchantNo = bankConfigManager.getFuminBankMch(queryMerchantDayBalanceDO.getBusinessOrderType());
            JSONObject jsonObject = new JSONObject();
            //商户号
            jsonObject.put("merchant_no", merchantNo);
            //日志流水号
            jsonObject.put("client_serial_no", leafUtil.getSnowflakeId());
            //当前页
            jsonObject.put("page_no", queryMerchantDayBalanceDO.getPageNo());
            //每页数量
            jsonObject.put("page_size", queryMerchantDayBalanceDO.getPageSize());
            //查询开始时间 开始时间例: 20181203
            jsonObject.put("start_date", queryMerchantDayBalanceDO.getStartTime());
            //查询结束时间 结束时间例: 20181205 (开始时间结束时间 相差 不超过 3 天)
            jsonObject.put("end_date", queryMerchantDayBalanceDO.getEndTime());

            OpenParameters.Builder builder = new OpenParameters.Builder();
            builder.apiName("com.fbank.open-api.api.v1.inteaccount.queryTradeDetailService")
                    .param(jsonObject.toJSONString());
            String response = springClient.send(builder.build(), merchantNo);
            log.info("FuminAdapter#queryMerchantRecord the TestTransfer request:{} response:{} ", JSONUtils.toJSON(jsonObject), response);
            JSONObject responseParam = JSON.parseObject(response);
            Map<String, String> headParam = JSONUtils.parse2Map(responseParam.getString("head"), String.class, String.class);

            if(!"000000".equals(headParam.get("rsp_code"))) {
                throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR.getCode(), headParam.get("rsp_msg"));
            }

            JSONObject bodyParam = JSONUtils.parse2Object(responseParam.getString("body"), JSONObject.class);
            return buildMerchantBalanceRecord(bodyParam);
        }
        catch(PaymentException e) {
            throw e;
        }
        catch(Exception e) {
            log.error("FuminAdapter#queryBalanceRecord error queryAccountBalanceDO:{}", JSON.toJSONString(queryMerchantDayBalanceDO), e);
            throw new PaymentException(ResultCodeEnum.CHANNEL_CONNECT_ERROR);
        }
    }

    /**
     * 组装对象
     * @param body
     * @return
     */
    private QueryDayBalanceRecordBo buildDayBalanceRecord(JSONObject body) {
        QueryDayBalanceRecordBo dayBalanceRecord = new QueryDayBalanceRecordBo();
        dayBalanceRecord.setPageNo(body.getString("page_no"));
        dayBalanceRecord.setPageSize(body.getString("page_size"));
        dayBalanceRecord.setTotalSize(body.getString("total_size"));
        dayBalanceRecord.setMerchantNo(body.getString("merchant_no"));
        List<DayBalanceRecordBo> balanceRecords = new ArrayList<>();
        dayBalanceRecord.setBalanceRecords(balanceRecords);

        JSONArray list = body.getJSONArray("balance_list");

        if(list != null && list.size() > 0) {
            for(int i = 0; i < list.size(); i++) {
                JSONObject object = list.getJSONObject(i);
                DayBalanceRecordBo item = new DayBalanceRecordBo();
                item.setDate(object.getString("check_date"));
                item.setBalance(object.getString("acct_balance"));
                balanceRecords.add(item);
            }
        }

        return dayBalanceRecord;
    }

    /**
     * 组装对象
     * @param body
     * @return
     */
    private QueryDayBalanceRecordBo buildMerchantBalanceRecord(JSONObject body) {
        QueryDayBalanceRecordBo dayBalanceRecord = new QueryDayBalanceRecordBo();
        dayBalanceRecord.setPageSize(body.getString("total_pages"));
        dayBalanceRecord.setTotalSize(body.getString("total_rows"));
        List<DayBalanceRecordBo> balanceRecords = new ArrayList<>();
        dayBalanceRecord.setBalanceRecords(balanceRecords);

        JSONArray list = body.getJSONArray("tran_hist_detail");

        if(list != null && list.size() > 0) {
            for(int i = 0; i < list.size(); i++) {
                JSONObject object = list.getJSONObject(i);
                DayBalanceRecordBo item = new DayBalanceRecordBo();
                item.setDate(object.getString("tran_time"));
                item.setBalance(object.getString("actual_bal_amt"));
                balanceRecords.add(item);
            }
        }

        return dayBalanceRecord;
    }

    private QueryFuminRecordBo buildQueryFuminRecordBo(JSONObject body) {
        QueryFuminRecordBo queryFuminRecordBo = new QueryFuminRecordBo();
        queryFuminRecordBo.setPageNo(Integer.parseInt((String) body.get("page_no")));
        queryFuminRecordBo.setTotalSize(Integer.parseInt((String) body.get("total_size")));
        List<FuminRecordBo> records = new ArrayList<>();
        List list = (List) body.get("balance_records");
        if (list != null && list.size() > 0) {
            for (Object recordStr : list) {
                records.add(buildFuminRecordBo((JSONObject) recordStr));
            }
        }
        queryFuminRecordBo.setRecords(records);
        return queryFuminRecordBo;
    }

    private FuminRecordBo buildFuminRecordBo(JSONObject record) {
        FuminRecordBo fr = new FuminRecordBo();
        fr.setAccountNo(record.getString("account_no"));
        fr.setTradeDate(record.getString("trade_date"));
        fr.setTradeFlowNo(record.getString("trade_flow_no"));
        fr.setFlowNo(record.getString("flow_no"));
        fr.setAmount(record.getString("amount"));
        fr.setBalance(record.getString("balance"));
        fr.setDirection(record.getString("direction"));
        fr.setHandStatus(record.getString("hand_status"));
        fr.setTradeType(record.getString("trade_type"));
        fr.setAccountIn(record.getString("account_in"));
        fr.setAccountInName(record.getString("account_in_name"));
        fr.setAccountOut(record.getString("account_out"));
        fr.setAccountOutName(record.getString("account_out_name"));
        fr.setMemo(record.getString("memo"));
        return fr;
    }

    /**
     * fbank_mock_pay_account_mapping_
     * @param accountId
     * @return
     */
    private String getAdapterAccountId(String accountId) {
        if(StringUtils.isBlank(accountId)) {
            return accountId;
        }

        try {
            String mappingAccountId = ApolloUtil.getProperty("fbank_mock_pay_account_mapping_" + accountId);
            log.info("------------fbank_mock_pay_account_mapping_" + accountId + "|" + mappingAccountId);
            return !StringUtils.isBlank(mappingAccountId) ? mappingAccountId : accountId;
        }
        catch(Exception ex) {
            log.error(ex.getMessage(), ex);
        }

        return accountId;
    }
}
